//=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|
// Funcao Histograma.
//________________________________________________________
//A.Z. - 01/06 => Criacao
//       03/07 => normalizedHistogram --> PeakNormalizedHistogram
//                Criei AreaNormalizedHistogram
//=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|
#ifndef HISTOGRAM_H
#define HISTOGRAM_H

#include <cmath>
#include <vector>
#include <algorithm>
#include "cpp/LIB/GENLIB/aborta.h"
#include "cpp/LIB/GENLIB/meusTipos.h"
using namespace std;



template<class T>
void PeakNormalizedHistogram(vector<T>&, vector<T>&, MTci &, const vector<T>& );
template<class T>
void AreaNormalizedHistogram(vector<T>&, vector<T>&, MTci &, const vector<T>& );
template<class T>
void histogram          ( vector<T>&, vector<T>&, MTci &, const vector<T>& );





//------------------------------------------------------------------------------
// DESCRICAO:
//   Usa a funcao histogram para retornar o histograma normalizado pelo pico
template<class T>
void PeakNormalizedHistogram( vector<T>& h, vector<T>& p, MTci &np,
                          const vector<T>& v ){
  histogram(h,p,np,v);
  typename vector<T>::iterator it = max_element( h.begin(), h.end() );
  T max = *it;
  for( it=h.begin(); it!=h.end(); it++ )
    *it = (*it)/max;
}





//------------------------------------------------------------------------------
// DESCRICAO:
//   Usa a funcao histogram para retornar o histograma normalizado pela area
template<class T>
void AreaNormalizedHistogram( vector<T>& h, vector<T>& p, MTci &np,
                          const vector<T>& v ){
  histogram(h,p,np,v);
  T sum=0;
  T dp = p[1]-p[0];
  int size = h.size();
  for( int i=0; i<size; i++ ) sum  += h[i];
  for( int i=0; i<size; i++ ) h[i] /= (sum*dp);
}





//------------------------------------------------------------------------------
// DESCRICAO:
//   Calcula um histograma com os dados em x.
// RECEBE:
//   h  => O histograma
//   p  => Posicoes onde o histograma foi calculado
//   np => Numero de posicoes no histograma
//   v  => Vector com os dados
// RETORNA:
//   Por referencia: h e p
template<class T>
void histogram( vector<T>& h, vector<T>& p, MTci &np, const vector<T>& v ){

  if(np<=0)     aborta("O numero de posicoes precisa ser positivo.");
  if(v.empty()) aborta("O vector com os dados estah vazio!");
  h.resize(np,0);
  p.resize(np,0);


  // Acha o maior e o menor valor de x
  typename vector<T>::const_iterator it;
  it = max_element( v.begin(), v.end() );  T max = *it;
  it = min_element( v.begin(), v.end() );  T min = *it;


  // Calcula o tamanhos dos passos e as posicoes do histograma
  // Neste algoritmo a abscissa eh dividida em tamanhos iguais. Se isso for
  //  mudado eh preciso alterar a funcao AreaNormalizedHistogram que assume isso
  T step = (max-min)/(1.0*np);
  p[0]   = (max-min)/(2.0*np) + min;
  for( int i=1; i<np; i++ )
    p[i] = p[i-1] + step;


  // Calcula o histograma
  int index;
  for( int i=0; i<v.size() ; i++){
    index = static_cast<int>( floor( ( v[i]-min )/(1.0*step) ) );

    if(index>np||index<0) aborta("Problema fatal na funcao!" );
    if( index==np       ) index--;

    h[index]++;
  }
}


#endif // HISTOGRAM_H
